package cn.cosmosx.base.security.service;

import cn.cosmosx.base.service.RedisService;
import cn.cosmosx.base.constant.GlobalConstant;
import cn.cosmosx.base.constant.ResultCode;
import cn.cosmosx.base.exception.PlatformException;
import cn.cosmosx.base.security.entity.SecurityUserVo;
import cn.cosmosx.base.util.BeanUtil;
import cn.cosmosx.base.encrypt.jwt.JWTsUtil;
import cn.cosmosx.base.util.FastHandlerUtils;
import cn.cosmosx.entity.sys.SysPerms;
import cn.cosmosx.entity.sys.SysRole;
import cn.cosmosx.entity.vo.RolePermsVO;
import cn.cosmosx.entity.vo.UserVO;
import cn.cosmosx.service.sys.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 缓存及token服务类
 */
@Component
public class CacheProviderService {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private RedisService redisService;

    /**
     * 保存 token 及 用户信息到缓存
     *
     * @param session - 用户bean
     * @param token   - token
     */
    public void saveToken(SecurityUserVo session, String token) {
        redisService.set(GlobalConstant.getAccessKey(session.getUserId(), token), session, GlobalConstant.LIFE_TIME);
    }

    /**
     * 查询 Redis用户缓存
     *
     * @param token - jwt
     * @return - SecurityUserVo
     */
    public SecurityUserVo getToken(String token) {
        String userId = JWTsUtil.parseJwt(token).getSubject();
        return redisService.get(GlobalConstant.getAccessKey(Long.valueOf(userId), token));
    }

    /**
     * 创建JWT token
     *
     * @param session - 用户bean
     * @return - token
     */
    public String createToken(SecurityUserVo session) {
        return JWTsUtil.token(String.valueOf(session.getUserId()));
    }

    /**
     * 刷新token缓存
     *
     * @param userId - 用户id
     */
    public void refreshCache(Long userId) {
        UserVO userVO = Optional.ofNullable(sysUserService.getRolesAndPermsById(userId, null))
                .orElseThrow(() -> new PlatformException(ResultCode.U90002));
        SecurityUserVo bean = BeanUtil.copyProperties(new SecurityUserVo(), userVO);
        Optional.ofNullable(userVO.getRoles()).ifPresent(roles -> {
            bean.setRoles(roles.stream().map(SysRole::getRoleCode).collect(Collectors.toSet()));
        });
        Optional.ofNullable(userVO.getPerms()).ifPresent(roles -> {
            bean.setPerms(roles.stream().map(SysPerms::getPermUrl).collect(Collectors.toSet()));
        });
        Set<String> tokenSet = redisService.listKeys(GlobalConstant.getAccessKeyPre(userId));
        tokenSet.forEach(key -> redisService.set(key, bean));
    }

    /**
     * 清除用户下的所有缓存
     *
     * @param userId - 用户id
     */
    public void clearCache(Long userId) {
        Set<String> tokenSet = redisService.listKeys(GlobalConstant.getAccessKeyPre(userId));
        redisService.delete(tokenSet);
    }

    /**
     * 获取并缓存所有的角色权限数据
     * @return - List
     */
    public List<RolePermsVO> getAndCacheRolePerms() {
        List<RolePermsVO> rolePerms = redisService.getList(GlobalConstant.PERMISSIONS);
        if (rolePerms == null || rolePerms.isEmpty()) {
            rolePerms = sysUserService.listRolePerms();
            List<RolePermsVO> finalRolePerms = rolePerms;
            FastHandlerUtils.notNullCall(rolePerms, () -> {
                // 初始化并缓存角色权限资源到Redis
                redisService.setList(GlobalConstant.PERMISSIONS, finalRolePerms);
            });
        }
        return rolePerms;
    }

    /**
     * 刷新角色权限缓存数据
     */
    public void refreshRolePermsCache() {
        List<RolePermsVO> rolePerms = sysUserService.listRolePerms();
        if (rolePerms != null && rolePerms.size() > 0) {
            redisService.setList(GlobalConstant.PERMISSIONS, rolePerms);
        }
    }
}
